package com.zb.sms.service;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.zb.entity.AccounLoginInfo;
import com.zb.entity.Sms;
import com.zb.entity.ZjAdmSmsTemplate;
import com.zb.enums.SmsCode;
import com.zb.exception.SMSException;
import com.zb.exception.ZbException;
import com.zb.service.ZjCustomerInfoService;
import com.zb.service.ZjSmsReceiveRoleService;
import com.zb.service.ZjSmsTemplateService;
import com.zb.service.impl.SmsLogService;
import com.zb.sms.entity.*;
import com.zb.util.SmsSendUtil;
import com.zb.utils.TemplateReplaceUtil;
import com.zb.vo.NetworkInviteCodeSendLogVo;
import com.zb.vo.SmsReceiveRoleVo;
import com.zb.vo.SmsSendLogVo;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;

/**
 * @Author WEN
 * @Date 2024/3/24 0024
 **/
@Service
public class SmsSendMessageService {
    private static Logger logger = LoggerFactory.getLogger(SmsSendMessageService.class);
    private static SmsSendMessageService smsSendMessageService;
    @PostConstruct
    public void init() {
        smsSendMessageService = this;
    }
    private static ZjAdmSmsTemplate admSmsTemplate;
    private static String templateParam;

    @Resource
    private ZjSmsTemplateService smsTemplateService;
    @Resource
    private ZjCustomerInfoService customerInfoService;
    @Resource
    private ZjSmsReceiveRoleService smsReceiveRoleService;

    /**
     * 发送工单新消息
     * @param loginInfo
     * @param receiveVo
     */
    public static void sendNewOrder(AccounLoginInfo loginInfo, OrderReceiveVo receiveVo) {
        String smsCode = SmsCode.WORK_NEW_CODE.getCode();
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("workNo", receiveVo.getWorkNo());
        send(loginInfo, smsCode, receiveVo, paramMap);
    }
    /**
     * 发送工单新消息
     * @param loginInfo
     * @param receiveVos
     */
    public static void sendNewOrder(AccounLoginInfo loginInfo, List<OrderReceiveVo> receiveVos) {
        String smsCode = SmsCode.WORK_NEW_CODE.getCode();
        ZjAdmSmsTemplate admSmsTemplate = smsSendMessageService.smsTemplateService.getAdmSmsTemplateBySmsCode(smsCode);
        if (null == admSmsTemplate) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, 2, smsCode, "", "", "", "", "短信发送失败，不存在的短信编号，请联系客服反馈！"));
            return;
        }
        if (admSmsTemplate.getDisabled()) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), "", "", "", "短信发送失败，该短信模板已下架，请联系客服反馈！"));
            return;
        }
        // 短信是否开启
        boolean enable = smsSendMessageService.smsTemplateService.isEnableByCode(loginInfo.getCustAccId(), smsCode);
        if (!enable) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), "", "", "", "商家已关闭短信发送通道，如要发送短信，请联系商家开启"));
            return;
        }
        // 短信余额是否充足
        boolean smsAbundant = smsSendMessageService.customerInfoService.isSmsAbundant(loginInfo.getCustAccId());
        SmsReceiveRoleVo receiveRoleVo = smsSendMessageService.smsReceiveRoleService.getRoleTypeBySmsCode(loginInfo.getCustAccId(), smsCode);
        List<SmsSendLogVo> sendSuccessList = new ArrayList<>();
        List<SmsSendLogVo> sendFailtList = new ArrayList<>();
        Map<String, String> paramMap = null;
        List<String> phones = null;
        String templateParam = null;
        for (OrderReceiveVo receiveVo : receiveVos) {
            phones = getOrderReceivePhone(loginInfo.getCustAccId(), smsCode, receiveRoleVo, receiveVo);
            if (CollectionUtil.isEmpty(phones)) {
                continue;
            }
            paramMap = new HashMap<>();
            paramMap.put("workNo", receiveVo.getWorkNo());
            for (String phone : phones) {
                try {
                    templateParam = TemplateReplaceUtil.template(admSmsTemplate.getContent() , paramMap);
                    if (!smsAbundant) {
                        sendFailtList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), phone, "", templateParam, "短信余额不足，发送失败！请联系商家及时充值"));
                        continue;
                    }
                    SmsSendUtil.sendSms(Sms.sms(smsCode, phone, JSON.toJSONString(paramMap)));
                    sendSuccessList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), phone, "", templateParam));
                } catch (Exception e) {
                    logger.error("工单取消通知发送失败：" + e);
                    e.printStackTrace();
                    sendFailtList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), phone, "", templateParam, e.getMessage()));
                }
            }
        }
        smsSendMessageService.customerInfoService.updateSmsBalanceById(loginInfo.getCustAccId(), sendSuccessList.size());
        SmsLogService.saveSuccess(sendSuccessList);
        SmsLogService.saveFailt(sendFailtList);
    }

    /**
     * 发送工单预约时间成功通知
     * @param loginInfo
     * @param receiveVo
     */
    public static void sendOrderReservationTime(AccounLoginInfo loginInfo, SendOrderReservationTimeVo receiveVo) {
        String smsCode = SmsCode.WORK_RESERVATION_TIME_CODE.getCode();
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("cName", receiveVo.getUsername());
        paramMap.put("workNo", receiveVo.getWorkNo());
        paramMap.put("engineer", receiveVo.getEngineer());
        paramMap.put("time", DateFormatUtils.format(receiveVo.getReservationDate(), "yyyy-MM-dd") + " " + DateFormatUtils.format(receiveVo.getReservationStartTime(), "HH:mm"));
        paramMap.put("etime", DateFormatUtils.format(receiveVo.getReservationEndTime(), "HH:mm"));
        send(loginInfo, smsCode, receiveVo, paramMap);
    }

    /**
     * 发送工单取消通知
     * @param loginInfo
     * @param receiveVo
     */
    public static void sendOrderCancel(AccounLoginInfo loginInfo, SendOrderCancelVo receiveVo) {
        String smsCode = SmsCode.WORK_CANCEL_CODE.getCode();
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("workNo", receiveVo.getWorkNo());
        paramMap.put("type", receiveVo.getModule());
        paramMap.put("state", receiveVo.getState());
        send(loginInfo, smsCode, receiveVo, paramMap);
    }

    /**
     * 发送工单取消通知
     * @param loginInfo
     * @param receiveVos
     */
    public static void sendOrderCancel(AccounLoginInfo loginInfo, List<SendOrderCancelVo> receiveVos) {
        String smsCode = SmsCode.WORK_CANCEL_CODE.getCode();
        ZjAdmSmsTemplate admSmsTemplate = smsSendMessageService.smsTemplateService.getAdmSmsTemplateBySmsCode(smsCode);
        if (null == admSmsTemplate) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, 2, smsCode, "", "", "", "", "短信发送失败，不存在的短信编号，请联系客服反馈！"));
            return;
        }
        if (admSmsTemplate.getDisabled()) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), "", "", "", "短信发送失败，该短信模板已下架，请联系客服反馈！"));
            return;
        }
        // 短信是否开启
        boolean enable = smsSendMessageService.smsTemplateService.isEnableByCode(loginInfo.getCustAccId(), smsCode);
        if (!enable) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), "", "", "", "商家已关闭短信发送通道，如要发送短信，请联系商家开启"));
            return;
        }
        // 短信余额是否充足
        boolean smsAbundant = smsSendMessageService.customerInfoService.isSmsAbundant(loginInfo.getCustAccId());
        SmsReceiveRoleVo receiveRoleVo = smsSendMessageService.smsReceiveRoleService.getRoleTypeBySmsCode(loginInfo.getCustAccId(), smsCode);
        List<SmsSendLogVo> sendSuccessList = new ArrayList<>();
        List<SmsSendLogVo> sendFailtList = new ArrayList<>();
        Map<String, String> paramMap = null;
        List<String> phones = null;
        String templateParam = null;
        for (SendOrderCancelVo receiveVo : receiveVos) {
            phones = getOrderReceivePhone(loginInfo.getCustAccId(), smsCode, receiveRoleVo, receiveVo);
            if (CollectionUtil.isEmpty(phones)) {
                continue;
            }
            paramMap = new HashMap<>();
            paramMap.put("workNo", receiveVo.getWorkNo());
            paramMap.put("type", receiveVo.getModule());
            paramMap.put("state", receiveVo.getState());
            for (String phone : phones) {
                try {
                    templateParam = TemplateReplaceUtil.template(admSmsTemplate.getContent() , paramMap);
                    if (!smsAbundant) {
                        sendFailtList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), phone, "", templateParam, "短信余额不足，发送失败！请联系商家及时充值"));
                        continue;
                    }
                    SmsSendUtil.sendSms(Sms.sms(smsCode, phone, JSON.toJSONString(paramMap)));
                    sendSuccessList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), phone, "", templateParam));
                } catch (Exception e) {
                    logger.error("工单取消通知发送失败：" + e);
                    e.printStackTrace();
                    sendFailtList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), phone, "", templateParam, e.getMessage()));
                }
            }
        }
        smsSendMessageService.customerInfoService.updateSmsBalanceById(loginInfo.getCustAccId(), sendSuccessList.size());
        SmsLogService.saveSuccess(sendSuccessList);
        SmsLogService.saveFailt(sendFailtList);
    }

    /**
     * 发送申请完工审核通知
     * @param loginInfo
     * @param receiveVo
     */
    public static void sendOrderFinish(AccounLoginInfo loginInfo, SendOrderFinishVo receiveVo) {
        String smsCode = SmsCode.WORK_FINISH_CODE.getCode();
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("result", receiveVo.getResult());
        paramMap.put("workNo", receiveVo.getWorkNo());
        paramMap.put("type", receiveVo.getType());
        send(loginInfo, smsCode, receiveVo, paramMap);
    }

    private static void send(AccounLoginInfo loginInfo, String smsCode, OrderReceiveVo receiveVo, Map<String, String> paramMap) {
        ZjAdmSmsTemplate admSmsTemplate = smsSendMessageService.smsTemplateService.getAdmSmsTemplateBySmsCode(smsCode);
        if (null == admSmsTemplate) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, 2, smsCode, "", "", "", "", "短信发送失败，不存在的短信编号，请联系客服反馈！"));
            return;
        }
        if (admSmsTemplate.getDisabled()) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), "", "", "", "短信发送失败，该短信模板已下架，请联系客服反馈！"));
            return;
        }
        // 短信是否开启
        boolean enable = smsSendMessageService.smsTemplateService.isEnableByCode(loginInfo.getCustAccId(), smsCode);
        if (!enable) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), "", "", "", "商家已关闭短信发送通道，如要发送短信，请联系商家开启"));
            return;
        }
        // 短信余额是否充足
        boolean smsAbundant = smsSendMessageService.customerInfoService.isSmsAbundant(loginInfo.getCustAccId());
        List<SmsSendLogVo> sendSuccessList = new ArrayList<>();
        List<SmsSendLogVo> sendFailtList = new ArrayList<>();
        List<String> phones = getOrderReceivePhone(loginInfo.getCustAccId(), smsCode, null, receiveVo);
        if (CollectionUtil.isEmpty(phones)) {
            return;
        }
        String templateParam = null;
        for (String phone : phones) {
            try {
                templateParam = TemplateReplaceUtil.template(admSmsTemplate.getContent() , paramMap);
                if (!smsAbundant) {
                    sendFailtList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), phone, "", templateParam, "短信余额不足，发送失败！请联系商家及时充值"));
                    continue;
                }
                SmsSendUtil.sendSms(Sms.sms(smsCode, phone, JSON.toJSONString(paramMap)));
                sendSuccessList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), phone, "", templateParam));
            } catch (Exception e) {
                logger.error("通知短信发送失败：" + e);
                e.printStackTrace();
                sendFailtList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), phone, "", templateParam, e.getMessage()));
            }
        }
        smsSendMessageService.customerInfoService.updateSmsBalanceById(loginInfo.getCustAccId(), sendSuccessList.size());
        SmsLogService.saveSuccess(sendSuccessList);
        SmsLogService.saveFailt(sendFailtList);
    }

    /**
     * 获取接收者手机号
     * @param smsCode
     * @param receiveVo
     * @return
     */
    private static List<String> getOrderReceivePhone(Long custAccId, String smsCode, SmsReceiveRoleVo receiveRoleVo, OrderReceiveVo receiveVo) {
        List<String> phones = new ArrayList<>();
        if (null == receiveRoleVo) {
            receiveRoleVo = smsSendMessageService.smsReceiveRoleService.getRoleTypeBySmsCode(custAccId, smsCode);
        }
        if (CollectionUtil.isEmpty(receiveRoleVo.getRoleTypes())) {
            return phones;
        }
        for (Integer roleType : receiveRoleVo.getRoleTypes()) {
            switch (roleType) {
                case 1 -> {
                    if (null != receiveVo.getEmpPhone()) phones.add(receiveVo.getEmpPhone());
                }
                case 2 -> {
                    phones.addAll(receiveRoleVo.getPhones().stream().filter(f -> !Objects.equals(f, receiveVo.getEmpPhone())).toList());
                }
                case 3 -> {
                    if (null != receiveVo.getNetworkManagerPhone()) phones.add(receiveVo.getNetworkManagerPhone());
                }
                case 4 ->{
                    if (null != receiveVo.getEngineerPhone()) phones.add(receiveVo.getEngineerPhone());
                }
                case 5 -> {
                    if (null != receiveVo.getUserPhone()) phones.add(receiveVo.getUserPhone());
                }
            }
        }
        return phones;
    }

    /**
     * 发送加入服务商的邀请码
     * @param loginInfo
     * @param phones 接收者手机号
     * @param param 短信模板字段属性
     */
    public static void sendInviteCode(AccounLoginInfo loginInfo, List<String> phones, Map<String, String> param) throws ZbException {
        String smsCode = SmsCode.NETWORK_INVITE_CODE.getCode();
        ZjAdmSmsTemplate admSmsTemplate = smsSendMessageService.smsTemplateService.getAdmSmsTemplateBySmsCode(smsCode);
        Assert.notNull(admSmsTemplate, "短信发送失败，不存在的短信编号，请联系客服反馈！");
        Assert.isFalse(admSmsTemplate.getDisabled(), "短信发送失败，该短信模板已下架，请联系客服反馈！");

        // 短信是否开启
        boolean enable = smsSendMessageService.smsTemplateService.isEnableByCode(loginInfo.getCustAccId(), smsCode);
        Assert.isTrue(enable, "商家已关闭短信发送通道，如要发送短信，请联系商家开启");

        String templateParam = TemplateReplaceUtil.template(admSmsTemplate.getContent() , param);
        List<SmsSendLogVo> sendSuccessList = new ArrayList<>();
        List<SmsSendLogVo> sendFailtList = new ArrayList<>();
        List<NetworkInviteCodeSendLogVo> sendSuccessInviteCodes = new ArrayList<>();
        List<NetworkInviteCodeSendLogVo> sendFailtInviteCodes = new ArrayList<>();
        for (String phone : phones) {
            try {
                SmsSendUtil.sendSms(Sms.sms(smsCode, phone, JSON.toJSONString(param)));
                sendSuccessList.add(SmsSendLogVo.sms(loginInfo, 3, smsCode, admSmsTemplate.getName(), phone, "",templateParam));
                sendSuccessInviteCodes.add(new NetworkInviteCodeSendLogVo(loginInfo.getCustAccId(), loginInfo.getName(), phone, templateParam));
            } catch (SMSException e) {
                logger.error("加入商家的邀请码的短信发送失败：" + e);
                e.printStackTrace();
                sendFailtList.add(SmsSendLogVo.sms(loginInfo, 3, smsCode, admSmsTemplate.getName(), phone, "", templateParam, e.getMessage()));
                sendFailtInviteCodes.add(new NetworkInviteCodeSendLogVo(loginInfo.getCustAccId(), loginInfo.getName(), phone, templateParam, e.getMessage()));
            }
        }
        smsSendMessageService.customerInfoService.updateSmsBalanceById(loginInfo.getCustAccId(), sendSuccessList.size());
        SmsLogService.saveSuccess(sendSuccessList);
        SmsLogService.saveFailt(sendFailtList);
        SmsLogService.saveInviteCodeSuccess(sendSuccessInviteCodes);
        SmsLogService.saveInviteCodeFailt(sendFailtInviteCodes);
    }

    /**
     * 工单催单
     * @param loginInfo
     * @param workRemindVoList
     */
    public static void sendWorkRemind(AccounLoginInfo loginInfo, List<SendWorkRemindVo> workRemindVoList) throws ZbException {
        String smsCode = SmsCode.WORK_REMIND_CODE.getCode();
        ZjAdmSmsTemplate admSmsTemplate = smsSendMessageService.smsTemplateService.getAdmSmsTemplateBySmsCode(smsCode);
        if (null == admSmsTemplate) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, 2, smsCode, "", "", "", "", "短信发送失败，不存在的短信编号，请联系客服反馈！"));
            return;
        }
        if (admSmsTemplate.getDisabled()) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), "", "", "", "短信发送失败，该短信模板已下架，请联系客服反馈！"));
            return;
        }
        // 短信是否开启
        boolean enable = smsSendMessageService.smsTemplateService.isEnableByCode(loginInfo.getCustAccId(), smsCode);
        if (!enable) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), "", "", "", "商家已关闭短信发送通道，如要发送短信，请联系商家开启"));
            return;
        }
        List<SmsSendLogVo> sendSuccessList = new ArrayList<>();
        List<SmsSendLogVo> sendFailtList = new ArrayList<>();
        Map<String, String> paramMap = new HashMap<>();
        String templateParam = null;
        for (SendWorkRemindVo remindVo : workRemindVoList) {
            paramMap.put("workNo", remindVo.getWorkNo());
            templateParam = TemplateReplaceUtil.template(admSmsTemplate.getContent() , paramMap);
            try {
                SmsSendUtil.sendSms(Sms.sms(smsCode, remindVo.getReceivePhone(), JSON.toJSONString(paramMap)));
                sendSuccessList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), remindVo.getReceivePhone(), remindVo.getReceiveUsername(), templateParam));
            } catch (SMSException e) {
                logger.error("工单催单短信发送失败：" + e);
                e.printStackTrace();
                sendFailtList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), remindVo.getReceivePhone(), remindVo.getReceiveUsername(), templateParam, e.getMessage()));
            }
        }
        smsSendMessageService.customerInfoService.updateSmsBalanceById(loginInfo.getCustAccId(), sendSuccessList.size());
        SmsLogService.saveSuccess(sendSuccessList);
        SmsLogService.saveFailt(sendFailtList);
    }

    /**
     * 发送手动触发工单节点超时提醒（手动触发提醒）
     * @param loginInfo
     * @param workTimeoutRemindVos
     * @throws ZbException
     */
    public static void sendManualTriggerWorkTimeoutRemind(AccounLoginInfo loginInfo, List<SendWorkTimeoutRemindVo> workTimeoutRemindVos) throws ZbException {
        if (CollectionUtil.isEmpty(workTimeoutRemindVos)) {
            return;
        }
        String smsCode = SmsCode.WORK_NODE_AFTER_TIMEOUT_REMIND_CODE_MANUAL_TRIGGER.getCode();
        ZjAdmSmsTemplate admSmsTemplate = smsSendMessageService.smsTemplateService.getAdmSmsTemplateBySmsCode(smsCode);
        Assert.notNull(admSmsTemplate, "短信发送失败，不存在的短信编号，请联系客服反馈！");
        Assert.isFalse(admSmsTemplate.getDisabled(), "短信发送失败，该短信模板已下架，请联系客服反馈！");
        // 短信是否开启
        boolean enable = smsSendMessageService.smsTemplateService.isEnableByCode(loginInfo.getCustAccId(), smsCode);
        Assert.isTrue(enable, "商家已关闭短信发送通道，如要发送短信，请联系商家开启");
        List<SmsSendLogVo> sendSuccessList = new ArrayList<>();
        List<SmsSendLogVo> sendFailtList = new ArrayList<>();
        Map<String, String> paramMap = new HashMap<>();
        String templateParam = null;
        for (SendWorkTimeoutRemindVo remindVo : workTimeoutRemindVos) {
            paramMap.put("Reminder", remindVo.getReminderNode());
            paramMap.put("workNo", remindVo.getWorkNo());
            paramMap.put("type", remindVo.getType());
            paramMap.put("state", remindVo.getState());
            templateParam = TemplateReplaceUtil.template(admSmsTemplate.getContent() , paramMap);
            try {
                SmsSendUtil.sendSms(Sms.sms(smsCode, remindVo.getReceivePhone(), JSON.toJSONString(paramMap)));
                sendSuccessList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), remindVo.getReceivePhone(), remindVo.getReceiveUsername(), templateParam));
            } catch (SMSException e) {
                logger.error("工单超时提醒短信发送失败：" + e);
                e.printStackTrace();
                sendFailtList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), remindVo.getReceivePhone(), remindVo.getReceiveUsername(), templateParam, e.getMessage()));
            }
        }
        smsSendMessageService.customerInfoService.updateSmsBalanceById(loginInfo.getCustAccId(), sendSuccessList.size());
        SmsLogService.saveSuccess(sendSuccessList);
        SmsLogService.saveFailt(sendFailtList);
    }

    /**
     * 发送工单节点超时提醒（根据SLA规则触发提醒）
     * @param loginInfo
     * @param workTimeoutRemindVos
     * @throws ZbException
     */
    public static void sendWorkTimeoutRemind(AccounLoginInfo loginInfo, List<SendWorkTimeoutRemindVo> workTimeoutRemindVos) throws ZbException {
        String smsCode = SmsCode.WORK_NODE_AFTER_TIMEOUT_REMIND_CODE_AUTO_TRIGGER.getCode();
        ZjAdmSmsTemplate admSmsTemplate = smsSendMessageService.smsTemplateService.getAdmSmsTemplateBySmsCode(smsCode);
        Assert.notNull(admSmsTemplate, "短信发送失败，不存在的短信编号，请联系客服反馈！");
        Assert.isFalse(admSmsTemplate.getDisabled(), "短信发送失败，该短信模板已下架，请联系客服反馈！");
        // 短信是否开启
        boolean enable = smsSendMessageService.smsTemplateService.isEnableByCode(loginInfo.getCustAccId(), smsCode);
        Assert.isTrue(enable, "商家已关闭短信发送通道，如要发送短信，请联系商家开启");
        List<SmsSendLogVo> sendSuccessList = new ArrayList<>();
        List<SmsSendLogVo> sendFailtList = new ArrayList<>();
        Map<String, String> paramMap = new HashMap<>();
        String templateParam = null;
        for (SendWorkTimeoutRemindVo remindVo : workTimeoutRemindVos) {
            paramMap.put("workNo", remindVo.getWorkNo());
            paramMap.put("type", remindVo.getType());
            paramMap.put("state", remindVo.getState());
            paramMap.put("Timeout", remindVo.getTimeout());
            paramMap.put("engineer", remindVo.getEngineer());
            templateParam = TemplateReplaceUtil.template(admSmsTemplate.getContent() , paramMap);
            try {
                SmsSendUtil.sendSms(Sms.sms(smsCode, remindVo.getReceivePhone(), JSON.toJSONString(paramMap)));
                sendSuccessList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), remindVo.getReceivePhone(), remindVo.getReceiveUsername(), templateParam));
            } catch (SMSException e) {
                logger.error("工单超时提醒短信发送失败：" + e);
                e.printStackTrace();
                sendFailtList.add(SmsSendLogVo.sms(loginInfo, 2, smsCode, admSmsTemplate.getName(), remindVo.getReceivePhone(), remindVo.getReceiveUsername(), templateParam, e.getMessage()));
            }
        }
        smsSendMessageService.customerInfoService.updateSmsBalanceById(loginInfo.getCustAccId(), sendSuccessList.size());
        SmsLogService.saveSuccess(sendSuccessList);
        SmsLogService.saveFailt(sendFailtList);
    }

    /**
     * 发送通知短信
     * @param loginInfo
     * @param smsCode 短信模板编号
     * @param receivePhone 接收者手机号
     * @param receiveUsername 接收者名称
     * @param param 短信模板字段属性
     */
    public synchronized static void sendNoticeSms(AccounLoginInfo loginInfo, String smsCode, String receivePhone, String receiveUsername, Map<String, String> param) {
        try {
            sendNoticeSms(false, loginInfo, smsCode, receivePhone, receiveUsername, param);
        } catch (SMSException e) {
        }
    }

    /**
     * 发送通知短信
     * @param throwException 是否抛出异常
     * @param loginInfo
     * @param smsCode
     * @param receivePhone
     * @param receiveUsername
     * @param param
     */
    public synchronized static void sendNoticeSms(boolean throwException, AccounLoginInfo loginInfo, String smsCode, String receivePhone, String receiveUsername, Map<String, String> param) throws SMSException {
        boolean sendSms = isSendSms(2, throwException, loginInfo, smsCode, receivePhone, receiveUsername, param);
        if (!sendSms) {
            return;
        }
        // 发送短信
        sendMessage(loginInfo, throwException, 2, smsCode, receivePhone, receiveUsername, param);
    }

    /**
     * 是否发送短信
     * @param type 短信类型：1-验证类短信，2-通知类，3-推广类短信
     * @param loginInfo
     * @param smsCode 短信编号
     * @param receivePhone 接收者手机号
     * @param receiveUsername 接收都姓名
     * @param param 短信模板参数字段属性
     * @return
     */
    private static boolean isSendSms(Integer type, boolean throwException, AccounLoginInfo loginInfo, String smsCode, String receivePhone, String receiveUsername, Map<String, String> param) throws SMSException {
        admSmsTemplate = smsSendMessageService.smsTemplateService.getAdmSmsTemplateBySmsCode(smsCode);
        if (null == admSmsTemplate) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, type, smsCode, "", receivePhone, receiveUsername, "", "短信发送失败，不存在的短信编号：" + smsCode));
            if (throwException) {
                throw new SMSException("短信发送失败，不存在的短信编号，请联系客服反馈！");
            }
            return false;
        }
        if (admSmsTemplate.getDisabled()) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, type, smsCode, admSmsTemplate.getName(), receivePhone, receiveUsername, admSmsTemplate.getContent(), "短信发送失败，该短信模板已下架，请联系客服反馈！"));
            if (throwException) {
                throw new SMSException("短信发送失败，该短信模板已下架，请联系客服反馈！");
            }
            return false;
        }
        try {
            templateParam = TemplateReplaceUtil.template(admSmsTemplate.getContent(), param);
        } catch (ZbException e) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, type, smsCode, admSmsTemplate.getName(), receivePhone, receiveUsername, admSmsTemplate.getContent(), e.getMessage()));
            if (throwException) {
                throw new SMSException(e.getMessage());
            }
            return false;
        }
        // 短信是否开启
        boolean enable = smsSendMessageService.smsTemplateService.isEnableByCode(loginInfo.getCustAccId(), smsCode);
        if (!enable) {
            SmsLogService.saveFailt(SmsSendLogVo.smsOff(loginInfo, type, smsCode, admSmsTemplate.getName(), receivePhone, receiveUsername, templateParam));
            if (throwException) {
                throw new SMSException("商家已关闭短信发送通道，如要发送短信，请联系商家开启");
            }
            return false;
        }
        // 短信余额是否充足
        boolean smsAbundant = smsSendMessageService.customerInfoService.isSmsAbundant(loginInfo.getCustAccId());
        if (!smsAbundant) {
            SmsLogService.saveFailt(SmsSendLogVo.smsBalanceoweFee(loginInfo, type, smsCode, admSmsTemplate.getName(), receivePhone, receiveUsername, templateParam));
            if (throwException) {
                throw new SMSException("商家短信数量不足，如要发送短信，请联系商家充值");
            }
            return false;
        }
        return true;
    }

    /**
     * 发送短信
     * @param loginInfo
     * @param smsCode 短信编号
     * @param receivePhone 接收者手机号
     * @param param 短信模板属性参数
     */
    private static void sendMessage(AccounLoginInfo loginInfo, boolean throwException, Integer type, String smsCode, String receivePhone, String receiveUsername, Map<String, String> param) throws SMSException {
        // 发送短信
        try {
            SmsSendUtil.sendSms(Sms.sms(smsCode, receivePhone, JSON.toJSONString(param)));
            smsSendMessageService.customerInfoService.updateSmsBalanceById(loginInfo.getCustAccId(), 1);
            SmsLogService.saveSuccess(SmsSendLogVo.sms(loginInfo, type, smsCode, admSmsTemplate.getName(), receivePhone, receiveUsername, templateParam));
        } catch (SMSException e) {
            SmsLogService.saveFailt(SmsSendLogVo.sms(loginInfo, type, smsCode, admSmsTemplate.getName(), receivePhone, receiveUsername, templateParam, e.getMessage()));
            if (throwException) {
                throw new SMSException(e.getMessage());
            }
        }
    }

}
